import React, { PureComponent } from 'react';
import { Button, Icon, notification } from 'antd';
import shortid from 'shortid';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import TextComponent from './TextComponent';
import RankComponent from './RankComponent';
// import VideoComponent from './VideoComponent';
import TitleComponent from './TitleComponent';
import ImageComponent from './ImageComponent';
// import GoodsComponent from './GoodsComponent';
// import TopicComponent from './TopicComponent';
// import ImgToSpuComponent from './ImgToSpuComponent';
import DividionComponent from './DividionComponent';
// import ItemGoodsComponent from './ItemGoodsComponent';
import styles from './index.less';

const basicType = {
  // 注意定义接口数据类型是 vedio 不是 video
  // vedio: { text: '视频', component: <VideoComponent /> },
  title: { text: '标题', component: <TitleComponent /> },
  subTitle: { text: '标题', component: <TitleComponent /> },
  text: { text: '文本', component: <TextComponent /> },
  image: { text: '图片', component: <ImageComponent /> },
  dividion: { text: '辅助分割', component: <DividionComponent /> },
  // goods: { text: '商品', component: <GoodsComponent /> },
  // topic: { text: '相关专题', component: <TopicComponent /> },
  // itemGoods: { text: '同类商品', component: <ItemGoodsComponent /> },
  // rank: { text: '企鹅评级', component: <RankComponent /> },
  // imgToSpu: { text: '图片导航', component: <ImgToSpuComponent /> },
};

function Content(type) {
  this.id = shortid.generate();
  this.type = type;
  this.comeponentType = `${type}Component`;
  this.content = type === 'dividion' ? 30 : undefined;
}

const Component = props => {
  const render = basicType[props.data.type].component;
  return render ? React.cloneElement(render, props) : null;
};

const reorder = (list, startIndex, endIndex) => {
  const result = [...list];
  const [removed] = result.splice(startIndex, 1);
  result.splice(endIndex, 0, removed);
  return result;
};

const getItemStyle = (isDragging, draggableStyle) => ({
  userSelect: 'none',
  background: isDragging ? '#fff' : 'transparent',
  boxShadow: isDragging ? '0 0 5px #fa541c' : 'none',
  transition: 'all 300ms',
  ...draggableStyle,
});

export function withRemove(WrappedComponent) {
  return class extends PureComponent {
    handleRemove = () => this.props.onRemove(this.props.data.id);

    render() {
      return (
        <div className={styles.wrapper}>
          <Icon
            className={styles.remove}
            onClick={this.handleRemove}
            type="close-circle"
            theme="twoTone"
          />
          <WrappedComponent {...this.props} onRemove={this.handleRemove} />
        </div>
      );
    }
  };
}

class ArticleEditor extends PureComponent {
  static defaultProps = {
    // 输入输出类型 string object
    type: 'string',
    // 只允许插入一段视频
    videoOnly: false,
    // 基础组件
    basic: ['vedio', 'title', 'text', 'image', 'dividion'],
  };

  static getDerivedStateFromProps(nextProps, prevState) {
    const { value, type } = nextProps;
    if (value && prevState.contentList.length === 0) {
      let contentList = null;
      if (value) {
        contentList = type === 'string' ? JSON.parse(value) : value;
      } else {
        contentList = [];
      }
      return { contentList };
    }
    return null;
  }

  constructor(props) {
    super(props);
    const { type, value } = this.props;
    let contentList = null;
    if (value) {
      contentList = type === 'string' ? JSON.parse(value) : value;
    } else {
      contentList = [];
    }
    this.state = { contentList };
  }

  addContent = type => {
    const { videoOnly } = this.props;
    const content = new Content(type);
    const hasVideo = this.state.contentList.some(v => v.type === 'vedio');
    if (videoOnly && hasVideo && type === 'vedio') {
      const key = `open${Date.now()}`;
      notification.warn({
        key,
        message: '温馨提示',
        description: '已经添加了一段视频, 重新添加将会覆盖前一段视频',
        btn: (
          <Button
            type="primary"
            onClick={() => {
              this.setState(
                prev => ({
                  contentList: prev.contentList.filter(v => v.type !== 'vedio').concat(content),
                }),
                () => this.onChange(this.state.contentList),
              );
              notification.close(key);
            }}
          >
            重新添加
          </Button>
        ),
      });
    } else {
      this.setState(
        prev => ({
          contentList: prev.contentList.concat(content),
        }),
        () => this.onChange(this.state.contentList),
      );
    }
  };

  handleChange = content => {
    const { contentList } = { ...this.state };
    contentList.forEach(item => {
      // eslint-disable-next-line no-param-reassign
      if (item.id === content.id) item = content;
    });
    this.onChange(contentList);
    this.setState({ contentList });
  };

  handleRemove = id => {
    this.setState(prevState => {
      const contentList = prevState.contentList.filter(v => v.id !== id);
      this.onChange(contentList);
      return { contentList };
    });
  };

  onChange = data => {
    const { type } = this.props;
    if (data.length === 0) {
      this.props.onChange();
    } else {
      this.props.onChange(type === 'string' ? JSON.stringify(data) : data);
    }
  };

  onDragEnd = result => {
    // 移除到列表之外
    if (!result.destination) return;
    const { contentList } = this.state;
    const items = reorder(contentList, result.source.index, result.destination.index);
    this.setState({ contentList: items });
    this.props.onChange(items);
  };

  render() {
    const { contentList } = this.state;
    const { basic } = this.props;
    return (
      <div className={styles.article}>
        <div className={styles.content}>
          <div className={styles.edit}>
            <DragDropContext onDragEnd={this.onDragEnd}>
              <Droppable droppableId="list">
                {provided => (
                  <div ref={provided.innerRef} {...provided.droppableProps}>
                    {contentList.map((item, index) => (
                      <Draggable key={item.id} draggableId={item.id} index={index}>
                        {(provided2, snapshot2) => (
                          <div
                            ref={provided2.innerRef}
                            {...provided2.draggableProps}
                            {...provided2.dragHandleProps}
                            style={getItemStyle(
                              snapshot2.isDragging,
                              provided2.draggableProps.style,
                            )}
                          >
                            <Component
                              data={item}
                              onChange={this.handleChange}
                              onRemove={this.handleRemove}
                            />
                          </div>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </DragDropContext>
          </div>
          <div className={styles.operation}>
            {basic.map(v => (
              <Button key={v} size="small" type="primary" onClick={() => this.addContent(v)}>
                {basicType[v].text}
              </Button>
            ))}
          </div>
        </div>
      </div>
    );
  }
}

export default ArticleEditor;
